package com.softer.chengxin.score.util;

import com.softer.chengxin.blacklist.dao.BlacklistDao;
import com.softer.chengxin.common.domin.Common;
import com.softer.chengxin.common.enums.LevelEnum;
import com.softer.chengxin.common.enums.NumberEnum;
import com.softer.chengxin.common.enums.ScoreTypeEnum;
import com.softer.chengxin.common.enums.SignEnum;
import com.softer.chengxin.common.util.DateFormatUtil;
import com.softer.chengxin.corp.dao.CorpDao;
import com.softer.chengxin.corp.domin.Corp;
import com.softer.chengxin.param.dao.GradeDao;
import com.softer.chengxin.param.entity.Grade;
import com.softer.chengxin.scheduled.dao.ScheduledTaskDao;
import com.softer.chengxin.score.dao.SDManagerDao;
import com.softer.chengxin.score.entity.Credit;
import com.softer.chengxin.score.entity.ScoreComposite;
import com.softer.chengxin.score.entity.ScoreDetail;
import com.softer.chengxin.score.entity.ServiceScore;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author Gong Zhiyang
 * @date 2019/1/21
 */
@Service
public class ScoreUtil {
    @Autowired
    private SDManagerDao managerDao;
    @Autowired
    private ScheduledTaskDao scheduledTaskDao;
    @Autowired
    private BlacklistDao blacklistDao;
    @Autowired
    private GradeDao gradeDao;
    @Autowired
    private CorpDao corpDao;

    /**
     * 修改企业record信息
     *
     * @param corpId 企业信息
     */
    public void updateRecord(Integer corpId) {
        //获取主管部门定义的年份
        String year = DateFormatUtil.getSysYear();
        if (StringUtils.isNotBlank(year)) {
            //得到当前年度该企业的detail信息
            List<ScoreDetail> scoreDetails = scheduledTaskDao.getScoreList(corpId);
            //得到该企业当前年度的record表信息
            ScoreComposite scoreComposite = managerDao.getScoreComposite(corpId, year);
            if (scoreComposite != null) {
                ScoreComposite sr = setScore(scoreDetails, scoreComposite, corpId, year);
                managerDao.updateScoreComposite(sr);
            } else {
                ScoreComposite sr = setScore(scoreDetails, new ScoreComposite(), corpId, year);
                managerDao.insertScoreComposite(sr);
            }
        }
    }

    public ScoreComposite setScore(List<ScoreDetail> scoreDetails, ScoreComposite scoreComposite, Integer corpId, String year) {
        BigDecimal excellentScore = BigDecimal.ZERO;
        BigDecimal negativeScore = BigDecimal.ZERO;
        if (scoreDetails != null && scoreDetails.size() > NumberEnum.ZERO.getNum()) {
            //计算优良总得分
            excellentScore = scoreDetails.stream().filter(o -> ScoreTypeEnum.EXCELLENT.getType().equals(o.getType())).map(ScoreDetail::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);
            //计算负面总得分
            negativeScore = scoreDetails.stream().filter(o -> ScoreTypeEnum.NEGATIVE.getType().equals(o.getType())).map(ScoreDetail::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        scoreComposite.setExcellentScore(excellentScore);
        scoreComposite.setNegativeScore(negativeScore);
        //计算企业的基础得分
        BigDecimal basicScore = getBasicScore(corpId, excellentScore, negativeScore, year);
        scoreComposite.setBasicScore(basicScore);
        //计算总得分
        BigDecimal allScore = basicScore.add(excellentScore).subtract(negativeScore);
        scoreComposite.setAllScore(allScore);
        String level = getLevel(allScore, corpId);
        scoreComposite.setLevel(level);
        scoreComposite.setCompanyId(corpId);
        scoreComposite.setYear(year);
        return scoreComposite;
    }

    /**
     * 获取企业的等级
     *
     * @param score 企业获得的分数
     * @param id    企业ID
     * @return 企业等级
     */
    public String getLevel(BigDecimal score, Integer id) {
        //查询企业是否在严重失信
        int corpInfoNum = blacklistDao.findCorpInfo(id);
        if (corpInfoNum > NumberEnum.ZERO.getNum()) {
            return LevelEnum.C_SERIOUS.getLevel();
        }
        List<Grade> list = gradeDao.getList();
        List<Grade> newList = new ArrayList<>();
        for (Grade grade : list) {
            if (compare(score, grade.getBiggerScore(), grade.getBiggerSign()) && compare(score, grade.getSmallerScore(), grade.getSmallerSign())) {
                newList.add(grade);
            }
        }
        if (newList.size() == NumberEnum.ONE.getNum()) {
            //如果只有一个区间，则返回当前区间的等级
            return newList.get(NumberEnum.ZERO.getNum()).getLevel();
        }
        if (newList.size() > NumberEnum.ONE.getNum()) {
            //如果存在多个区间，则判断是否存在有效期内的不良信息
            int num = managerDao.getBadInfoNum(id) == NumberEnum.ZERO.getNum() ? NumberEnum.ZERO.getNum() : NumberEnum.ONE.getNum();
            Optional<Grade> first = newList.stream().filter(x -> x.getBadInfo() == num).findFirst();
            if (first.isPresent()) {
                return first.get().getLevel();
            }
        }
        return "-";
    }

    /**
     * 根据运算符比较 两个数大小
     *
     * @param score    计算的分数
     * @param standard 数据库的标准
     * @param sign     比较符号
     * @return 比较结果
     */
    private boolean compare(BigDecimal score, BigDecimal standard, String sign) {
        if (SignEnum.GREATER.getSign().equals(sign)) {
            return score.compareTo(standard) > NumberEnum.ZERO.getNum();
        } else if (SignEnum.GREATER_OR_EQUAL.getSign().equals(sign)) {
            return score.compareTo(standard) >= NumberEnum.ZERO.getNum();
        } else if (SignEnum.LESS.getSign().equals(sign)) {
            return score.compareTo(standard) < NumberEnum.ZERO.getNum();
        } else if (SignEnum.LESS_OR_EQUAL.getSign().equals(sign)) {
            return score.compareTo(standard) <= NumberEnum.ZERO.getNum();
        }
        return false;
    }

    /**
     * 计算企业总得分
     *
     * @param corpId 企业ID
     * @return 总得分
     */
    public BigDecimal getBasicScore(Integer corpId, BigDecimal excellentScore, BigDecimal negativeScore, String year) {
        //企业基本信息分数
        BigDecimal companyBasicScore = new BigDecimal(40);
        //企业党建信息分数
        BigDecimal partyScore = getPartyScore(corpId);
        //企业缴纳保险和公积金员工数，不足20人 1分；20-50 2分； 50-100 3分；>100 4分
        BigDecimal personScore = getPerson(corpId);
        //企业管理技术人员情况
        BigDecimal artisanScore = getArtisanScore(corpId);
        //企业员工素质情况
        BigDecimal staffScore = getStaffScore(corpId);
        //企业经营情况分数
        BigDecimal corpManageScore = getCorpManage(corpId);
        //物业服务规模分数
        BigDecimal serviceScore = getServiceScore(corpId);
        //参与保障性住房，老旧小区服务分数
        BigDecimal oldScore = getOldScore(corpId);

        //增加企业信用分数
        Credit credit = new Credit(corpId, year, companyBasicScore, partyScore, personScore, artisanScore, staffScore, corpManageScore, serviceScore, oldScore, excellentScore, negativeScore);
        managerDao.addOrUpdateCredit(credit);
        //返回企业基础总得分
        return companyBasicScore.add(partyScore).add(personScore).add(artisanScore).add(staffScore).add(corpManageScore).add(serviceScore).add(oldScore);
    }

    /**
     * 企业员工素质情况
     *
     *
     * @param corpId 企业Id
     * @return 分数
     */
    private BigDecimal getStaffScore(Integer corpId) {
        //查询项目经理分数，1查询审核通过的项目的数量，2 查询这些项目下有审核通过的培训的数量
        BigDecimal managerScore = BigDecimal.ZERO;
        int projectNum = managerDao.getPassProjectNum(corpId);
        if (projectNum > 0) {
            //查询这些项目下有审核通过的培训的数量
            int trainNum = managerDao.getTrainNum(corpId);
            double rate = BigDecimal.valueOf((float) trainNum / projectNum).setScale(NumberEnum.TWO.getNum(), BigDecimal.ROUND_HALF_UP).doubleValue();
            if (rate >= Common.ZERO_POINT_SIX && rate < Common.ZERO_POINT_SEVEN) {
                managerScore = new BigDecimal(NumberEnum.TWO.getNum());
            } else if (rate >= Common.ZERO_POINT_SEVEN && rate < Common.ZERO_POINT_EIGHT) {
                managerScore = new BigDecimal(NumberEnum.THREE.getNum());
            } else if (rate >= Common.ZERO_POINT_EIGHT) {
                managerScore = new BigDecimal(NumberEnum.FOUR.getNum());
            }
        }

        //查询所有人员数量
        int personNum = managerDao.getAllPersonNum(corpId);
        //获取企业持相关职业资格证书所有人员数量
        int certificatePersonNum = managerDao.getCertificatePersonNum(corpId);
        if (personNum > NumberEnum.ZERO.getNum()) {
            double rate = BigDecimal.valueOf((float) certificatePersonNum / personNum).setScale(NumberEnum.TWO.getNum(), BigDecimal.ROUND_HALF_UP).doubleValue();
            if (rate >= Common.ZERO_POINT_SEVEN && rate < Common.ZERO_POINT_EIGHT) {
                return new BigDecimal(NumberEnum.ONE.getNum()).add(managerScore);
            } else if (rate >= Common.ZERO_POINT_EIGHT) {
                return new BigDecimal(NumberEnum.TWO.getNum()).add(managerScore);
            }
        }
        return managerScore;
    }

    /**
     * 企业管理技术人员情况
     * 查询企业人员中 选择了 具备 相关专业中级以上职称 的人员数量
     *
     * @param corpId 企业Id
     * @return 分数
     */
    private BigDecimal getArtisanScore(Integer corpId) {
        //获取企业持相关职业资格证书所有人员数量
        int artisanScoreNum = managerDao.getArtisanScore(corpId);
        if (artisanScoreNum >= NumberEnum.TWO.getNum() && artisanScoreNum < NumberEnum.FOUR.getNum()) {
            return new BigDecimal(NumberEnum.TWO.getNum());
        }
        if (artisanScoreNum >= NumberEnum.FOUR.getNum() && artisanScoreNum < NumberEnum.SIX.getNum()) {
            return new BigDecimal(NumberEnum.THREE.getNum());
        }
        if (artisanScoreNum >= NumberEnum.SIX.getNum() && artisanScoreNum < NumberEnum.EIGHT.getNum()) {
            return new BigDecimal(NumberEnum.FOUR.getNum());
        }
        if (artisanScoreNum >= NumberEnum.EIGHT.getNum()) {
            return new BigDecimal(NumberEnum.FIVE.getNum());
        }
        return BigDecimal.ZERO;
    }

    /**
     * 企业党建信息分数
     * 企业创建党支部，得2分
     * 红色物业，得1分
     * 四位一体，得2分
     *
     * @param corpId 企业Id
     * @return 分数
     */
    private BigDecimal getPartyScore(Integer corpId) {
        BigDecimal partyScore = BigDecimal.ZERO;
        Corp corpInfo = corpDao.getCorpInfo(corpId);
        if (corpInfo != null) {
            //企业创建党支部，得2分
            if (Common.ONE.equals(corpInfo.getOrganization())) {
                partyScore = partyScore.add(new BigDecimal(NumberEnum.TWO.getNum()));
            }
            //红色物业，得1分
            if (Common.ONE.equals(corpInfo.getRedProperty())) {
                partyScore = partyScore.add(new BigDecimal(NumberEnum.ONE.getNum()));
            }
            //四位一体，得2分
            if (Common.ONE.equals(corpInfo.getQuaternity())) {
                partyScore = partyScore.add(new BigDecimal(NumberEnum.TWO.getNum()));
            }
        }
        return partyScore;
    }

    /**
     * 参与保障性住房，老旧小区服务分数
     *
     * @param corpId 企业ID
     * @return 分数
     */
    private BigDecimal getOldScore(Integer corpId) {
        BigDecimal oldScore = corpDao.getOldScore(corpId);
        if (oldScore != null) {
            BigDecimal score = oldScore.divide(new BigDecimal(NumberEnum.THREE.getNum()), NumberEnum.ZERO.getNum(), BigDecimal.ROUND_DOWN);
            BigDecimal multiply = score.multiply(new BigDecimal(Common.ZERO_POINT_FIVE));
            if (multiply.compareTo(new BigDecimal(NumberEnum.FOUR.getNum())) >= 0) {
                return new BigDecimal(NumberEnum.FOUR.getNum());
            }
            return multiply;
        }
        return BigDecimal.ZERO;
    }

    /**
     * 物业服务规模分数
     *
     * @param corpId 企业ID
     * @return 分数
     */
    private BigDecimal getServiceScore(Integer corpId) {
        //获取项目数量和项目总面积
        ServiceScore serviceScore = corpDao.getServiceScore(corpId);
        //物业项目数量得分
        int num = serviceScore.getNum() / NumberEnum.THREE.getNum();
        if (num > NumberEnum.FIVE.getNum()) {
            num = NumberEnum.FIVE.getNum();
        }
        //物业服务面积得分
        BigDecimal score = BigDecimal.ZERO;
        if (serviceScore.getArea() != null) {
            score = serviceScore.getArea().divide(BigDecimal.TEN, NumberEnum.ZERO.getNum(), BigDecimal.ROUND_DOWN);
            if (score.compareTo(new BigDecimal(NumberEnum.FIVE.getNum())) > NumberEnum.ZERO.getNum()) {
                score = new BigDecimal(NumberEnum.FIVE.getNum());
            }
        }
        return new BigDecimal(num).add(score);
    }

    /**
     * 企业经营情况分数
     *
     * @param corpId 企业ID
     * @return 分数
     */
    private BigDecimal getCorpManage(Integer corpId) {
        //
        Corp corpInfo = corpDao.getCorpInfo(corpId);
        String creditContract = corpInfo.getCreditContract();
        //守合同重信用企业或放心消费创建示范单位分数
        BigDecimal creditScore = BigDecimal.ZERO;
        if (String.valueOf(NumberEnum.ONE.getNum()).equals(creditContract)) {
            creditScore = new BigDecimal(NumberEnum.TWO.getNum());
        }
        //第一份合同时间
        String firstContractTime = corpInfo.getFirstContractTime();
        if (StringUtils.isEmpty(firstContractTime)) {
            return creditScore;
        }
        LocalDate parse = LocalDate.parse(firstContractTime);
        Period pe = Period.between(parse, LocalDate.now());
        int years = pe.getYears();
        BigDecimal timeScore = new BigDecimal(years).multiply(new BigDecimal(Common.ZERO_POINT_FIVE));
        //企业经营情况，最高6分
        return creditScore.add(timeScore).compareTo(new BigDecimal(NumberEnum.SIX.getNum())) > NumberEnum.ZERO.getNum() ? new BigDecimal(NumberEnum.SIX.getNum()) : creditScore.add(timeScore);
    }

    /**
     * 获取企业员工数分数
     *
     * @param corpId 企业Id
     * @return 分数
     */
    private BigDecimal getPerson(int corpId) {
        int personNum = managerDao.getCorpPersonNum(corpId);
        if (personNum < NumberEnum.TWENTY.getNum()) {
            return BigDecimal.ONE;
        }
        if (personNum >= NumberEnum.TWENTY.getNum() && personNum < NumberEnum.FIFTY.getNum()) {
            return new BigDecimal(NumberEnum.TWO.getNum());
        }
        if (personNum >= NumberEnum.FIFTY.getNum() && personNum < NumberEnum.ONE_HUNDRED.getNum()) {
            return new BigDecimal(NumberEnum.THREE.getNum());
        }
        return new BigDecimal(NumberEnum.FOUR.getNum());
    }

    /**
     * 获取企业等级
     *
     * @param score 分数
     * @return 级别
     */
    public String getLevel(BigDecimal score) {
        BigDecimal sixty = new BigDecimal(60);
        BigDecimal eighty = new BigDecimal(80);
        BigDecimal ninety = new BigDecimal(90);

        if (score == null || score.compareTo(sixty) < 0) {
            return LevelEnum.D.getLevel();
        }
        if (score.compareTo(sixty) >= 0 && score.compareTo(eighty) < 0) {
            return LevelEnum.A.getLevel();
        }
        if (score.compareTo(eighty) >= 0 && score.compareTo(ninety) < 0) {
            return LevelEnum.AA.getLevel();
        }
        if (score.compareTo(ninety) >= 0) {
            return LevelEnum.AAA.getLevel();
        }
        return LevelEnum.A.getLevel();
    }

}
